﻿using Pseudogenerator.Common.Checkers;
using Pseudogenerator.Common.Checkers.Core;
using Pseudogenerator.Common.Generators.Core;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace Pseudogenerator.Common.ViewModels.Core
{
    public abstract class WorkSpaceViewModel : ViewModelBase
    {
        public abstract bool CanRun { get; }

        private ObservableCollection<RandomNumber> _Results = null;
        public ObservableCollection<RandomNumber> Results
        {
            get
            {
                return _Results ?? new ObservableCollection<RandomNumber>();
            }
            protected set
            {
                _Results = value;
            }
        }

        #region CommonBindings

        public abstract string Title { get; }

        public abstract IEnumerable<string> Errors { get; }
        public abstract IEnumerable<string> Recommendations { get; }

        private ICommand runCommand = null;
        public ICommand RunCommand
        {
            get
            {
                if (runCommand == null)
                    runCommand = new RelayCommand("Ejecutar",
                        a => Run(),
                        p => CanRun
                    );
                return runCommand;
            }
        }
        private void Run()
        {
            OnPropertyChanged("ErrorMessage");
            OnPropertyChanged("Tests");
            InWorkProgress = true;

            AddPreload();

            LoadResults();
        }

        protected abstract void LoadSync();

        private async void LoadResults()
        {
            await Task.Factory.StartNew(() =>
            {
                LoadSync();
            });
        }

        private ICommand clearCommand = null;
        public ICommand ClearCommand
        {
            get
            {
                if (clearCommand == null)
                    clearCommand = new RelayCommand("Limpiar datos",
                        a => Clear()
                    );
                return clearCommand;
            }
        }
        private void Clear()
        {
            this.Results.Clear();
            OnPropertyChanged("Results");
        }

        public ICollection<ICommand> actionCommands = null;
        public ICollection<ICommand> ActionCommands
        {
            get
            {
                if (actionCommands == null)
                {
                    actionCommands = new List<ICommand>();
                    actionCommands.Add(RunCommand);
                    actionCommands.Add(ClearCommand);
                }
                return actionCommands;
            }
        }

        public void RefreshGUI()
        {
            OnPropertyChanged("Errors");
            OnPropertyChanged("Recommendations");
            OnPropertyChanged("CanRun");
        }

        public KeyValuePair<string, bool>[] Tests
        {
            get
            {
                var t = new List<KeyValuePair<string, bool>>();
                foreach (var item in _Tests)
                {
                    var r = false;
                    try
                    {
                        r = item.Test(Results.ToList());
                    }
                    catch
                    {
                        r = false;
                    }

                    t.Add(new KeyValuePair<string, bool>(item.TestName, r));
                }
                return t.ToArray();
            }
        }


        protected abstract void AddPreload();

        private bool _InWorkProgress = false;
        public bool InWorkProgress
        {
            get
            { return _InWorkProgress; }
            set
            {
                if (_InWorkProgress == value)
                    return;
                _InWorkProgress = value;
                OnPropertyChanged();
            }
        }

        private List<TestBase> _tests = null;
        private List<TestBase> _Tests
        {
            get
            {
                _tests = new List<TestBase>()
                {
                    new AverageTest(), 
                    new FrequencyTest(5),
                    new KolmogorovSmirnovTest(),
                    new NumbersAsDigitsDistanceTest(5),
                    new NumbersAsRealsDistanceTest(5,0.1,0.8),
                    new SeriesTest(),
                    new PokerTest(),
                    new AboveAndBelowTheAverageRunsTest(),
                    new UpAndDownRunsTest(),  
                };
                return _tests;
            }
        }

        #endregion



        #region metodos de ayuda

        protected static bool SonPrimosRelativos(double a, double b)
        {
            var f1 = new List<int>();
            var f2 = new List<int>();
            for (int i = 1; i <= a; i++)
                if (a % i == 0)
                    f1.Add(i);

            for (int i = 1; i <= b; i++)
                if (b % i == 0)
                    f2.Add(i);


            for (int i = 0; i < f1.Count; i++)
                if (f2.Contains(f1[i]) && f1[i] != 1)
                    return false;

            return true;
        }

        protected static bool MultiplosDePrimosImparesDe(double valor, double m)
        {
            var multImp = new List<int>();
            for (int i = 1; i < m; i += 2)
                if (i % m == 0)
                    if (i % valor != 0)
                        return false;

            return true;
        }

        #endregion
    }
}
